﻿using EnvDTE;
using EnvDTE80;
using Microsoft;
using System.Reflection;

namespace Single.Generate
{
    internal class Generate
    {
        private const string SolutionName = "Single";
        private const string ServiceFolder = "4.业务模块";
        private const string DirectoryName = "net8.0";
        private const string VisualStudioDTE = "VisualStudio.DTE.17.0"; // 注册表 VisualStudio.DTE -- CurVer 值

        private string path;
        private Solution solution;
        private string solutionConfiguration;

        public void ExecuteGenerate()
        {
            Console.WriteLine("初始化 VisualStudio.DTE 中...");
            DTE dte = (DTE)Activator.CreateInstance(Type.GetTypeFromProgID(VisualStudioDTE));

            Console.WriteLine("正在加载解决方案...");
            path = Environment.CurrentDirectory;
            path = path.Substring(0, path.IndexOf($"{SolutionName}.Generate"));
            dte.Solution.Open($"{path}{SolutionName}.sln");
            Assumes.Present(dte);
            solution = dte.Solution;
            solutionConfiguration = solution.SolutionBuild.ActiveConfiguration.Name;

            try
            {
                Console.WriteLine("正在读取业务模块...");
                GetProjects(solution.Projects, ServiceFolder).ForEach(BuildProject);

                Console.WriteLine("执行完毕");
            }
            catch (Exception)
            {
                throw;
            }
            finally { solution.Close(); dte.Quit(); }
        }

        private List<Project> GetProjects(Projects projects, string folder)
        {
            List<Project> list = new List<Project>();

            foreach (Project project in projects)
            {
                if (project.Kind.Equals(ProjectKinds.vsProjectKindSolutionFolder))
                {
                    if (project.Name.Equals(folder))
                    {
                        foreach (ProjectItem item in project.ProjectItems)
                        {
                            list.Add(item.SubProject);
                        }
                    }
                }
            }

            return list;
        }

        private void BuildProject(Project project)
        {
            Console.WriteLine($"正在生成 {project.Name} 项目...");

            solution.SolutionBuild.BuildProject(solutionConfiguration, project.FullName, true);

            string areaPath = project.FullName.Replace($@"\{project.Name}.csproj", string.Empty);

            var assemblyFile = $@"{areaPath}\bin\{solutionConfiguration}\{DirectoryName}\{project.Name}.dll";

            var types = Assembly.LoadFrom(assemblyFile).GetTypes().Where(m => m.Namespace == $"{project.Name}.Entity").ToList();

            ServiceGenerate(areaPath, project.Name, types.Select(m => m.Name).ToList());
        }

        private void ServiceGenerate(string areaPath, string area, List<string> list)
        {
            foreach (var item in list)
            {
                T4.Service t4 = new T4.Service(SolutionName, area, item);
                ClassFileWrite($@"{areaPath}\Service", $@"\{item}Service.cs", t4.TransformText(), false);
            }

            ServicePropsGenerate(areaPath, area, list);
        }

        private void ServicePropsGenerate(string areaPath, string area, List<string> list)
        {
            T4.ServiceProps t4 = new T4.ServiceProps(SolutionName, area, list);
            ClassFileWrite(areaPath, @"\ServiceProps.cs", t4.TransformText(), true);
        }

        private void ClassFileWrite(string path, string file, string text, bool cover)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            string filename = $"{path}{file}";

            if (!File.Exists(filename) || cover)
            {
                File.WriteAllText(filename, text);
            }

            Console.WriteLine($"生成文件:{path}{file}");
        }
    }
}